#include "updatedialog.h"
#include "ui_updatedialog.h"
#include "datamanagement/mainwindows/mainwindow.h"
#include "datamanagement/userdefine/userdefine.h"
#include "commonform.h"
#include <QSqlQuery>

updateDialog::updateDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::updateDialog)
{
    ui->setupUi(this);
    // 去掉问号，设置最小化、最大化、关闭
    setWindowFlags(Qt::Dialog | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
    setWindowTitle("修改数据");
}

void updateDialog::initLayOut(int updateId)
{
    this->updateId = updateId;
    // 加载自定义修改界面样式
    userDefinedlayout();
}

updateDialog::~updateDialog()
{
    delete ui;
    // 循环删除界面输入框对象
    QList<QLineEdit*> edits =  inputTextMap.values();
    for(QLineEdit* edit: edits) {
        delete edit;
    }
    // 清理映射集
    inputTextMap.clear();
}

void updateDialog::on_update_pushButton_clicked()
{ 
    // 设置主界面进度条5秒后到达90%
    ((MainWindow*) UserDefineConstant::MAIN_WINDOW)->changeProgressBar(5, 90);
    // 开启一个加载提示框
    LoadingDialog* loading = LoadingDialog::createLoading(this);
    // 获取父窗体
    CommonForm* commonForm = (CommonForm*) parentWidget();
    // 创建一个异步线程监听器
    QFutureWatcher<QPair<bool,MessageInfo>> *pwatcher = new QFutureWatcher<QPair<bool,MessageInfo>>;

    // 异步执行耗时操作（异步相当于重新开了个子线程去执行，所以异步里面执行的内容在子线程中，子线程中不能修改和创建GUI的对象），这里用到了lambda表达式,自行搜索c++lambda表达式
    // 对异步操作有疑问：https://blog.csdn.net/nchu_zhangyiqing/article/details/114291400
    // 对c++lambda有疑问：https://blog.csdn.net/qq_37085158/article/details/124626913
    QFuture<QPair<bool,MessageInfo>> future = QtConcurrent::run([=]() {
        // 获取父页面对应的表信息
        UserDefineTableEntity userDefineTableEntity = commonForm->getTable();
        qDebug()<<"进入修改"+userDefineTableEntity.tableZnName+"数据操作";
        QList<int> ids = inputTextMap.keys();
        qDebug()<<"自定义id列："<< ids;
        QList<ColumnEntity> columnEntuitys = DataBaseOpt::selectColumnTableByIds(ids); // 查找出该表对应的所有列
        qDebug()<<"自定义列信息大小："<< columnEntuitys.size();

        QMap<QString,QString> columnValues;
        // 循环每列数据，取出每列的对应的输入框的值进行判断
        for(ColumnEntity entity: columnEntuitys) {
            QLineEdit* lineEdit = inputTextMap.value(entity.id);
            QString text = lineEdit->text();
            // 当前列如果是不允许为空，则如果是空值则提示错误信息
            if(entity.columnIsRequired == UserDefineConstant::BOOL_ZN_NAME_TRUE && ObjectUtil::isEmpty(text)) {
                return QPair<bool,MessageInfo>(false, MessageInfo("提示", entity.columnZnName+"请输入完整"));;
            }
            // 当前列如果是具有唯一性，则不满足唯一性则提示错误信息
            if(entity.columnIsUnique == UserDefineConstant::BOOL_ZN_NAME_TRUE) {
                QList<QueryConditions> conditions;
                conditions.append(QueryConditions(entity.columnName, text, false, "=" , "and"));
                conditions.append(QueryConditions(UserDefineConstant::ID_COLUMN_NUIQUE_NAME, QString::number(updateId),true, "!=" , "and"));
                int count = DataBaseOpt::selectAllCount(userDefineTableEntity.tableName,conditions); // 这里查找是否除了本身还有其他相同内容的列
                if(count > 0) {
                    return QPair<bool,MessageInfo>(false, MessageInfo("提示", entity.columnZnName+"已存在，请重新输入"));;
                }
            }
            // 通过验证后记录下该列对应值
            columnValues.insert(entity.columnName, text);
        }
        bool isSucess = DataBaseOpt::updateTableById(userDefineTableEntity.tableName, updateId, columnValues);
        if(isSucess)
        {
            return QPair<bool,MessageInfo>(true, MessageInfo("成功","修改成功"));
        }
        return QPair<bool,MessageInfo>(false, MessageInfo("失败","修改失败"));
    });

    // 绑定异步耗时操作执行完成后的后续操作（也就是监听结束的操作）（该后续操作是在主线程中的，可以操作GUI对象）
    connect(pwatcher, &QFutureWatcher<QPair<bool,MessageInfo>>::finished, this, [=]()
    {
        QPair<bool,MessageInfo> result = pwatcher->future().result();
        // 设置主界面进度条立即到达100%
        ((MainWindow*) UserDefineConstant::MAIN_WINDOW)->changeProgressBar(0, 100);
        // 关闭加载提示框
        loading->close();
        if(result.first) {
            close();
            // 刷新列表
            commonForm->autoUserdefineTableReflash(false);
        }
        // 提示信息放在最后，避免阻塞前面内容的执行
        QMessageBox::information(this,result.second.title, result.second.msg);
    });
    pwatcher->setFuture(future); // 设置监听器监听内容为异步操作的返回内容（也就是绑定监听的内容，这里是绑定异步耗时操作）
}

void updateDialog::userDefinedlayout()
{
    // 删除窗口所有布局
    QLayout *dlayout = layout();
    delete dlayout;

    CommonForm* commonForm = (CommonForm*) parentWidget();
    UserDefineTableEntity userDefineTableEntity = commonForm->getTable();
    QList<ColumnEntity> columnEntitys = commonForm->getCurrentObjectAllColumn();  // 获取父窗口表格所有的列信息
    qDebug()<<"修改页面查询出列数："<<columnEntitys.size();

    // 组装列名集合
    QList<QString> columns;
    for(ColumnEntity columnEntity:columnEntitys) {
        columns.append(columnEntity.columnName);
    }
    // 组装查询条件（id查询条件）
    QList<QueryConditions> conditions;
    conditions.append(QueryConditions(UserDefineConstant::ID_COLUMN_NUIQUE_NAME, QString::number(updateId), true, "=" , "and"));
    // 查询数据库对应的当前行的数据
    QList<QMap<QString,QString>> result = DataBaseOpt::selectTable(userDefineTableEntity.tableName, columns, conditions);
    // 如果数据库里面没有，则提示错误信息
    if(result.size() == 0) {
        QMessageBox::information(this,"初始化页面失败","所选择数据为空");
        return;
    }
    QMap<QString,QString> data = result.at(0);
    QGridLayout* gridLayout = new QGridLayout();

    // 循环所有的列信息，为每列创建对应的输入框，并将列对应的id和输入框进行绑定
    int row = 0;
    for(ColumnEntity columnEntity:columnEntitys) {
        QLineEdit* lineEdit = new QLineEdit();
        lineEdit->setText(data.value(columnEntity.columnName, ""));
        gridLayout->addWidget(new QLabel(columnEntity.columnZnName),row,0,1,1); // 添加标题
        gridLayout->addWidget(lineEdit,row,1,1,1); // 添加输入框
        inputTextMap.insert(columnEntity.id, lineEdit); // 记录列id和对应输入框的映射关系
        row++;
        qDebug()<<"添加页面创建数据行："<< row;
    }
    QPushButton* submitBtn = new QPushButton("修改");
    connect(submitBtn,SIGNAL(clicked()),this,SLOT(on_update_pushButton_clicked())); // 绑定提交按钮的点击事件
    QVBoxLayout* vBoxLayout = new QVBoxLayout();
    vBoxLayout->addLayout(gridLayout);
    vBoxLayout->addWidget(submitBtn);
    setLayout(vBoxLayout);
}
